package com.simple.space.modules.base.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.simple.space.common.exception.BusinessException;
import com.simple.space.common.exception.ErrorCode;
import com.simple.space.modules.base.dao.MyMapper;
import com.simple.space.modules.base.pojo.Base;
import com.simple.space.modules.base.service.IBaseService;
import org.apache.commons.beanutils.PropertyUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public abstract class BaseServiceImpl<T extends Base, PK extends java.io.Serializable> implements IBaseService<T, PK> {

    public abstract MyMapper<T> getMapper();

    @Override
    public int insert(T entity) throws BusinessException {
        try {
            return getMapper().insert(entity);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_INSERT, e.getMessage(), e);
        }
    }

    @Override
    public int insertSelective(T entity) throws BusinessException {
        try {
            return getMapper().insertSelective(entity);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_INSERT, e.getMessage(), e);
        }
    }

    @Override
    public int save(T entity) throws BusinessException {
        try {
            return this.insertSelective(entity);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_INSERT, e.getMessage(), e);
        }
    }

    @Override
    public int delete(PK key) throws BusinessException {
        try {
            return getMapper().deleteByPrimaryKey(key);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_DELETE, e.getMessage(), e);
        }
    }

    @Override
    public int deleteByExample(Object example) throws BusinessException {
        try {
            return getMapper().deleteByExample(example);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_DELETE, e.getMessage(), e);
        }
    }

    @Override
    public int delete(T entity) throws BusinessException {
        try {
            return getMapper().delete(entity);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_DELETE, e.getMessage(), e);
        }
    }

    @Override
    public int deleteByPrimaryKey(PK key) throws BusinessException {
        try {
            return getMapper().deleteByPrimaryKey(key);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_DELETE, e.getMessage(), e);
        }
    }

    @Override
    public int updateByPrimaryKey(T entity) throws BusinessException {
        try {
            return getMapper().updateByPrimaryKey(entity);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_UPDATE, e.getMessage(), e);
        }
    }

    @Override
    public int updateByPrimaryKeySelective(T entity) throws BusinessException {
        try {
            return getMapper().updateByPrimaryKeySelective(entity);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_UPDATE, e.getMessage(), e);
        }
    }

    @Override
    public int updateAll(T entity) throws BusinessException {
        try {
            return getMapper().updateByPrimaryKeySelective(entity);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_UPDATE, e.getMessage(), e);
        }
    }

    @Override
    public int updateNotNull(T entity) throws BusinessException {
        try {
            return getMapper().updateByPrimaryKeySelective(entity);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_UPDATE, e.getMessage(), e);
        }
    }

    @Override
    public int updateByExample(Example example, T entity) throws BusinessException {
        try {
            return getMapper().updateByExampleSelective(entity, example);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_UPDATE, e.getMessage(), e);
        }
    }

    @Override
    public int selectCount(T entity) throws BusinessException {
        try {
            return getMapper().selectCount(entity);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
        }
    }

    @Override
    public int selectCountByExample(Example example) throws BusinessException {
        try {
            return getMapper().selectCountByExample(example);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
        }
    }

    @Override
    public List<T> select(T entity) throws BusinessException {
        try {
            return getMapper().select(entity);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
        }
    }

    @Override
    public T selectByPrimaryKey(PK key) throws BusinessException {
        try {
            return getMapper().selectByPrimaryKey(key);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
        }
    }

    @Override
    public PageInfo<T> selectPage(int pageNum, int pageSize, T entity) throws BusinessException {
        try {
            return selectPage(pageNum, pageSize, entity, null);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
        }
    }

    @Override
    public PageInfo<T> selectPage(T entity) throws BusinessException {
        try {
            return selectPage(entity.getPageNum(), entity.getPageSize(), entity, entity.getOrderSqlStr());
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
        }
    }

    @Override
    public PageInfo<T> selectPage(int pageNum, int pageSize, T entity, String orderSqlStr) throws BusinessException {
        try {
            Example example = new Example(entity.getClass(), false, false);
            Example.Criteria criteria = example.createCriteria();
            Map<String, Object> map;
            map = null == entity ? new HashMap<>() : PropertyUtils.describe(entity);
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                if (entry.getValue() == null || "".equals(entry.getValue())) continue;
                criteria.andEqualTo(entry.getKey(), entry.getValue());
            }

            if (null != orderSqlStr && !"".equals(orderSqlStr)) {
                example.setOrderByClause(orderSqlStr);
            }

            PageHelper.startPage(pageNum, pageSize);
            List<T> list = getMapper().selectByExample(example);

            return new PageInfo<T>(list);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
        }
    }

    @Override
    public T selectOne(T entity) throws BusinessException {
        try {
            List<T> results = getMapper().select(entity);
            if (results != null && results.size() > 0) {
                return results.get(0);
            } else {
                return null;
            }
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
        }
    }

    @Override
    public T selectByKey(PK key) throws BusinessException {
        try {
            if(null == key) {
                return null;
            }
            return getMapper().selectByPrimaryKey(key);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
        }
    }

    @Override
    public List<T> selectByExample(Example example) throws BusinessException {
        try {
            return getMapper().selectByExample(example);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
        }
    }

    @Override
    public List<T> selectAllEntities() throws BusinessException {
        try {
            return getMapper().selectByExample(null);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
        }
    }

    @Override
    public PageInfo<T> selectPagingByExample(Object example, int pageNum, int pageSize) throws BusinessException {
        try {
            PageHelper.startPage(pageNum, pageSize);
            List<T> dataList = getMapper().selectByExample(example);
            return new PageInfo<T>(dataList);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
        }
    }
}
